#include "FleetAttackFleet.hh"
#include "Done.hh"
#include "XmlServerThread.hh"
#include "../World/Fleet.hh"
#include "../World/Fleet/AttackFleet.hh"
#include "../Exception.hh"

using namespace Network;
using namespace World;

struct FafFleetInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.fleet_attack_planet.fleet invalid");
    }
};

struct FafTargetPlayerInvalid {
    void operator () () {
        throw NonFatalProtocolError(
          "game.fleet_attack_planet.target_player invalid"
        );
    }
};

struct FafTargetFleetInvalid {
    void operator () () {
        throw NonFatalProtocolError(
          "game.fleet_attack_planet.target_fleet invalid"
        );
    }
};

spFleetAttackFleet FleetAttackFleet::construct(QDomElement const& message) {
    QDomElement const fleetElem = message.firstChildElement("fleet");
    QDomElement const targetPlayerElem =
      message.firstChildElement("target_player");
    QDomElement const targetFleetElem =
      message.firstChildElement("target_fleet");
    return spFleetAttackFleet(new FleetAttackFleet(
      ::parse_num< u8, FafFleetInvalid >(fleetElem),
      ::parse_str< FafTargetPlayerInvalid >(targetPlayerElem),
      ::parse_num< u8, FafTargetFleetInvalid >(targetFleetElem)
    ));
}

FleetAttackFleet::FleetAttackFleet(
  u8 fleetId, QString const& targetPlayerId, u8 targetFleetId
):
    fleetId(fleetId),
    targetPlayerId(targetPlayerId),
    targetFleetId(targetFleetId) {}

void FleetAttackFleet::process_on_server(XmlServerThread& thread) {
    if (thread.get_state() != GAME)
        throw NonFatalProtocolError("game.fleet_attack_fleet unexpected");

    try {
        spPlayer player = thread.get_player();
        spFleet fleet = player->get_fleet(fleetId);
        spPlayer targetPlayer =
          player->get_galaxy()->get_player(User::select(targetPlayerId).data());
        spFleet targetFleet = targetPlayer->get_fleet(targetFleetId);
        fleet->set_command(new Fleet::AttackFleet(targetFleet));
        Done done(true, "game.fleet_attack_fleet ok");
        done.send_to(*thread.get_socket());
    } catch (FleetNotFound& ex) {
        Done done(false, ex.what());
        done.send_to(*thread.get_socket());
    }
}

QDomDocument FleetAttackFleet::to_xml() const {
    QDomDocument doc;
    QDomElement gameElem = doc.createElement("game");
    QDomElement fleetAttackFleetElem = doc.createElement("fleet_attack_fleet");
    doc.appendChild(gameElem);
    gameElem.appendChild(fleetAttackFleetElem);
    ::to_xml(fleetAttackFleetElem, "fleet",  fleetId);
    ::to_xml(fleetAttackFleetElem, "target_player", targetPlayerId);
    ::to_xml(fleetAttackFleetElem, "target_fleet", targetFleetId);
    return doc;
}
